import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.filechooser.*;

import com.formdev.flatlaf.*;

public class WDTMain extends JFrame {
    private Container c = getContentPane();
    private JMenuBar menuBar = new JMenuBar();
    private JMenu fileMenu = new JMenu("文件");
    private JMenu editMenu = new JMenu("编辑");
    private JMenu viewMenu = new JMenu("查看");
    private JMenu aboutMenu = new JMenu("关于");
    private EnhancedTab tabPane = new EnhancedTab();
    private int newFileCnt = 0;
    private boolean easterEntry = false;
    private FontFrame fontframe = null;
    private void addTextArea(String filename, File f, String text) {
        CodeEdit ta = new CodeEdit(f);
        if (text.length() == 0) {
            ta.setText("a");
        }
        ta.setText(text);
        tabPane.appendTab(filename, ta);
    }
    private void initMenu() {
        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        menuBar.add(viewMenu);
        menuBar.add(aboutMenu);
        JMenuItem aboutAbout = new JMenuItem("关于 Windows Development Tool...");
        aboutAbout.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (newFileCnt <= 15 || (!easterEntry)) JOptionPane.showMessageDialog(null, "Windows Development Tool 是一个 Python 语言的 IDE，后期将会添加 Java 语言支持。\n开源地址：https://gitee.com/foolish-shabby/wdteditor", "关于 Windows Development Tool", JOptionPane.INFORMATION_MESSAGE);
                else if (easterEntry) {
                    JOptionPane.showMessageDialog(null, "恭喜你发现了彩蛋！\n在什么地方，好像有一个不知名的菜单项出现了……", "BOOM", JOptionPane.INFORMATION_MESSAGE);
                    newFileCnt = -2147483647;
                    JMenuItem item = new JMenuItem("运行……？");
                    item.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent evt) {
                            JOptionPane.showMessageDialog(null, "程序运行结束，谢谢您的使用。\n愿我们终有一日能够重逢，不过最好还是不要在这个地方吧。", "Windows Development Tool 已崩溃", JOptionPane.ERROR_MESSAGE);
                            System.exit(0);
                        }
                    });
                    fileMenu.add(item);
                }
            }
        });
        aboutMenu.add(aboutAbout);
        JMenuItem editFAR = new JMenuItem("查找与替换...");
        editFAR.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                new FindAndReplace(WDTMain.this).showup();
            }
        });
        editMenu.add(editFAR);
        editFAR.setAccelerator(KeyStroke.getKeyStroke('F', InputEvent.CTRL_DOWN_MASK));
        JMenuItem viewFont = new JMenuItem("字体设置...");
        viewFont.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                int n = 0;
                Object[] options = {"我要继续！", "我保证我以后就调大小……"};
                n = JOptionPane.showOptionDialog(null, "由于 Windows 自带字体依赖 fallback 机制，大多无法显示中文，因此在更改的字体后可能会导致中文显示异常。\n同时，默认字体不自带粗体和斜体，如果不更换字体的话，只能更改字体大小。\n因未知原因，如果只修改大小，下方预览文字的字体为 Arial 而非实际字体，仅供参考。\n是否继续修改字体？", "警告", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options);
                int r = new Random(System.currentTimeMillis()).nextInt(100);
                if (r >= 94) {
                    JOptionPane.showMessageDialog(null, "你已经被警告过了。", "我才不会告诉你这是可以触发彩蛋的标志呢", JOptionPane.INFORMATION_MESSAGE);
                    easterEntry = true;
                }
                new FontFrame(WDTMain.this, n == 0).showup();
            }
        });
        viewMenu.add(viewFont);
        JMenuItem viewHex = new JMenuItem("进入/退出十六进制查看模式");
        viewHex.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (tabPane.getSelectedComponent() instanceof CodeEdit) {
                    CodeEdit ta = (CodeEdit) tabPane.getSelectedComponent();
                    HexView hex = new HexView(ta.getFile());
                    hex.setText("a");
                    hex.setText(ta.getText());
                    tabPane.setComponentAt(tabPane.getSelectedIndex(), hex);
                } else if (tabPane.getSelectedComponent() instanceof HexView) {
                    HexView hex = (HexView) tabPane.getSelectedComponent();
                    CodeEdit ta = new CodeEdit(hex.getFile());
                    ta.setText("a");
                    ta.setText(hex.getText());
                    tabPane.setComponentAt(tabPane.getSelectedIndex(), ta);
                }
            }
        });
        viewMenu.add(viewHex);
        viewHex.setAccelerator(KeyStroke.getKeyStroke('H', InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK));
        JMenuItem fileNew = new JMenuItem("新建文件");
        JMenuItem fileOpen = new JMenuItem("打开");
        JMenuItem fileSave = new JMenuItem("保存");
        JMenuItem fileSaveAs = new JMenuItem("另存为...");
        JMenuItem fileExit = new JMenuItem("退出");
        fileMenu.add(fileNew);
        fileMenu.add(fileOpen);
        fileMenu.addSeparator();
        fileMenu.add(fileSave);
        fileMenu.add(fileSaveAs);
        fileMenu.addSeparator();
        fileMenu.add(fileExit);
        fileNew.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                addTextArea("未命名", null, "");
                newFileCnt++;
            }
        });
        fileOpen.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JFileChooser chooser = new JFileChooser();
                chooser.setFileFilter(new FileNameExtensionFilter("Python File", "py", "pyw"));
                int flag = chooser.showOpenDialog(WDTMain.this);
                if (flag == JFileChooser.APPROVE_OPTION) {
                    File currentFile = chooser.getSelectedFile();
                    boolean found = false;
                    for (int i = 0; i < tabPane.componentCount(); i++) {
                        if (tabPane.getTitleAt(i).equals(currentFile.getName())) {
                            CodeEdit ta = (CodeEdit) tabPane.getComponentAt(i);
                            ta.setText(FileUtil.readFile(currentFile, "UTF-8"));
                            tabPane.setSelectedIndex(i);
                            found = true;
                            break;
                        }
                    }
                    if (!found) addTextArea(currentFile.getName(), currentFile, FileUtil.readFile(currentFile, "UTF-8"));
                }
            }
        });
        fileSave.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                CodeEdit ta = (CodeEdit) tabPane.getSelectedComponent();
                File currentFile = ta.getFile(); 
                if (currentFile != null) {
                    FileUtil.saveFile(currentFile, "UTF-8", ta.getText());
                } else {
                    JFileChooser chooser = new JFileChooser();
                    chooser.setFileFilter(new FileNameExtensionFilter("Python File", "py", "pyw"));
                    int flag = chooser.showSaveDialog(WDTMain.this);
                    if (flag == JFileChooser.APPROVE_OPTION) {
                        currentFile = chooser.getSelectedFile();
                        ta.setFile(currentFile);
                        tabPane.setSelectedTitle(currentFile.getName());
                        FileUtil.saveFile(currentFile, "UTF-8", ta.getText());
                    }
                }
            }
        });
        fileSaveAs.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                CodeEdit ta = (CodeEdit) tabPane.getSelectedComponent();
                JFileChooser chooser = new JFileChooser();
                chooser.setFileFilter(new FileNameExtensionFilter("Python File", "py", "pyw"));
                int flag = chooser.showSaveDialog(WDTMain.this);
                if (flag == JFileChooser.APPROVE_OPTION) {
                    File currentFile = chooser.getSelectedFile();
                    ta.setFile(currentFile);
                    tabPane.setSelectedTitle(currentFile.getName());
                    FileUtil.saveFile(currentFile, "UTF-8", ta.getText());
                }
            }
        });
        fileExit.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        fileNew.setAccelerator(KeyStroke.getKeyStroke('N', InputEvent.CTRL_DOWN_MASK));
        fileOpen.setAccelerator(KeyStroke.getKeyStroke('O', InputEvent.CTRL_DOWN_MASK));
        fileSave.setAccelerator(KeyStroke.getKeyStroke('S', InputEvent.CTRL_DOWN_MASK));
        fileSaveAs.setAccelerator(KeyStroke.getKeyStroke('S', InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK));
        fileExit.setAccelerator(KeyStroke.getKeyStroke('Q', InputEvent.CTRL_DOWN_MASK));
    }
    private void initWindow() {
        setSize(1024, 768);
        setLayout(new BorderLayout());
        setVisible(true);
        setDefaultCloseOperation(3);
        c.add(tabPane);
        addTextArea("未命名", null, "");
        setJMenuBar(menuBar);
    }
    public WDTMain() {
        super("Windows Development Tool");
        initMenu();
        initWindow();
    }
    public static void main(String[] args) {
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            public void uncaughtException(Thread thread, Throwable ex) {
                StringWriter writer = new StringWriter();
                ex.printStackTrace(new PrintWriter(writer));
                String str = writer.toString();
                int clip = str.length() < 1250 ? str.length() : 1250;
                str = str.substring(0, clip) + "...";
                JOptionPane.showMessageDialog(null, "这不是你的问题，这是我们的问题，异常调用栈如下：\n" + str, "喔唷，崩溃啦！", JOptionPane.ERROR_MESSAGE);
            }
        });
        try {
            UIManager.setLookAndFeel( new FlatLightLaf() );
        } catch( Exception ex ) {
            System.err.println( "Failed to initialize LaF" );
        }
        new WDTMain();
    }
    public EnhancedTab getTabPane() {
        return tabPane;
    }
}